package previous.Test_0120;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Created with Intellij IDEA
 * Description:
 * User: 星辰
 */
public class Solution {
    //有效三角形个数
    //暴力解法:暴力枚举三个判断
    //优解：单调性，双指针
    //1.排序：固定最大值
    //2.如果a+b<=c,left++;
    //3.a+b>c,right--;个数：right-left
    public int validTriangleNumber (int[] nums) {
        int len=nums.length;
        int sum=0;
        Arrays.sort(nums);
        for (int i = 0; i <= len-2; i++) {
            int left=0;
            int right=len-2-i;
            int max=nums[len-1-i];
            while(left<right){
                if(nums[left]+nums[right]<=max){
                    left++;
                }else{
                    sum+=right-left;
                    right--;
                }
            }
        }
        return sum;
    }
    //和为S的两个数字
    //单调性，双指针
    //如果left+right>target;rigth--;
    //否则left++
    public int[] FindNumbersWithSum(int [] array,int sum) {
        int left=0;
        int len=array.length;
        int right=len-1;
        while(left<right){
            if(array[left]+array[right]>sum){
                right--;
            }else if(array[left]+array[right]<sum){
                left++;
            }else{
                return new int[]{array[left],array[right]};
            }
        }
        return null;
    }
    //三数之和
    /*给定一个包含 n 个整数的数组 nums，判断 nums 中是否存在三个元素 a ，b ，c ，
    使得 a + b + c = 0 ？请找出所有和为 0 且 不重复 的三元组。*/
    //双指针
    //1.排序;
    //2.固定一个数；
    //3.后面指针利用双指针来寻找相反数
    /*排序，从小到大；
    固定一个数，left，right寻找最值，查看有无重复的数，有，就跳过；
    如果没有，将固定值向后移动，left向后移动*/
    public List<List<Integer>> threeSum(int[] nums) {
         Arrays.sort(nums);
        List<List<Integer>> n=new ArrayList<>();
         int len=nums.length;
        for (int i = 0; i < len-2; i++) {
            int a=nums[i];
            if(a>0){
                break;
            }
            int left=i+1;
            int right=len-1;
            while(left<right){
                //left和right下标两个数之和
                int sum=nums[left]+nums[right];
                //如果等于，那么将其放入顺序表中
                if(sum+a==0){
                    //注意这个要用new，新的一个对象，否则会重复
                    n.add(new ArrayList<Integer>(Arrays.asList(a,nums[left],nums[right])));
                    left++;
                    right--;
                    //如果大于，说明right--
                    while(left<right && nums[left]==nums[left-1] ){
                        left++;
                    }
                    //right与其后面的进行比较，如果相同向后移动
                    while(left<right && right+1<len && nums[right]==nums[right+1] ){
                        right--;
                    }
                }else if(sum+a>0){
                    right--;
                    //小于，left++；
                }else{
                    left++;
                }
                //去重，防止越界，要left<right,
                //如果left与其前一个相同，去重，向后移动

            }
            //固定的值夜要跳过固定的元素
            while(i<len-2 && nums[i+1]==nums[i]){
                i++;
            }
        }
        return n;
    }
    //四数之和
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> ret=new ArrayList<>();
        Arrays.sort(nums);
        int len=nums.length;
        for (int i = 0; i <len-2; i++) {
            int ret1=nums[i];
            for (int j = i+1; j < len-1; ) {
                int ret2=nums[j];
                for (int left = j+1,right=len-1; left<right;) {
                    long sum=nums[right]+nums[left];
                    long cmp=ret1+ret2+sum;
                    if(cmp>target){
                        right--;
                    }else if(cmp<target){
                        left++;
                    }else{
                        List<Integer> n=new ArrayList<>();
                        n.add(ret1);
                        n.add(ret2);
                        n.add(nums[left]);
                        n.add(nums[right]);
                        ret.add(n);
                        while(left<right && nums[left]==nums[left+1]){
                            left++;
                        }
                        while(left<right && nums[right]==nums[right-1]){
                            right--;
                        }
                        left++;
                        right--;
                    }
                }
                j++;
                while(j<len && nums[j]==nums[j-1]){
                    j++;
                }
            }
            i++;
            while(i<len && nums[i]==nums[i-1]){
                i++;
            }
            }
        return ret;
        }
    }